セキュリティグループの変更・追加・削除を Microsoft Teams に通知する仕組みをCloudFormationでテンプレート化してみた
こんにちは!AWS事業本部のおつまみです。
みなさん、セキュリティグループの変更・追加・削除を検知して、Teamsに通知してほしいなぁと思ったことはありますか?私はあります。
通知することで、不正や意図しない変更を迅速に把握し、対応することが可能になります。
今回は通知する仕組みをCloudFormationテンプレートで構築できるようにしたので、紹介します!
このような通知画面となります。
実装方法はこちらのブログを参考にしました。
構成図
今回構築する構成です。
前提として、CloudTrailが既に有効化されている環境で構築します。
セキュリティグループを変更(追加・削除)してから、Teams通知するまでの流れ
-
セキュリティグループの変更(追加・削除):
ユーザーまたはAWSサービスがセキュリティグループに対して変更(追加・削除)を実施 -
CloudTrailによるログ記録:
AWS CloudTrailが、この変更をイベントとして記録 -
EventBridgeルールのトリガー:
設定されたEventBridgeルール(このテンプレートのEventsRule
リソース)が、CloudTrailのイベントを検知 -
イベントデータの変換:
EventBridgeルールのInputTransformerが、検知したイベントデータを、Teamsに送信するための適切な形式に変換 -
API Destinationの呼び出し:
変換されたデータが、設定されたAPI Destination(EventsApiDestination
リソース)に送信 -
TeamsのWebhookへの送信:
API DestinationがTeamsのWebhook URLにPOSTリクエストを送信 -
Teamsでの通知表示:
TeamsがWebhookからのデータを受け取り、指定されたチャンネルに通知を表示
CloudFormationテンプレートを準備
テンプレート内容は以下の通りです。
テンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: 'sg-change-resource-notify-teams'
Parameters:
SystemPrefix:
Type: String
EnvPrefix:
Type: String
Default: test
AllowedValues:
- prd
- test
- dev
- poc
WebhookURL:
Type: String
NoEcho: true
MentionedUserMailAddress:
Description: xxx@example.com
Type: String
NoEcho: true
MentionedUserName:
Type: String
Resources:
IAMManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: EventBridgePolicyForSecurityHubNotifytoTeams
Path: /service-role/
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- events:InvokeApiDestination
Resource:
- !GetAtt EventsApiDestination.Arn
IAMRole:
Type: AWS::IAM::Role
Properties:
Path: /service-role/
RoleName: !Sub ${SystemPrefix}-${EnvPrefix}-eventbridge-teams-api-dest-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: events.amazonaws.com
Action: sts:AssumeRole
MaxSessionDuration: 3600
ManagedPolicyArns:
- !Ref IAMManagedPolicy
EventsRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub ${SystemPrefix}-${EnvPrefix}-nw-notify-teams
EventPattern:
detail-type:
- AWS API Call via CloudTrail
source:
- "aws.ec2"
detail:
eventSource: ["ec2.amazonaws.com"]
eventName:
- AuthorizeSecurityGroupIngress
- AuthorizeSecurityGroupEgress
- RevokeSecurityGroupIngress
- RevokeSecurityGroupEgress
State: ENABLED
Targets:
- Arn: !GetAtt EventsApiDestination.Arn
HttpParameters:
HeaderParameters: {}
QueryStringParameters: {}
Id: EventsRuleName
InputTransformer:
InputPathsMap:
AwsAccountId: '$.account'
SecuritygroupId: '$.detail.requestParameters.groupId'
eventId: '$.id'
time: '$.time'
userName: '$.detail.userIdentity.sessionContext.sessionIssuer.userName'
eventName: '$.detail.eventName'
region: '$.region'
InputTemplate: !Sub |
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "\u003cat\u003e${MentionedUserName}\u003c/at\u003e \n\n# **セキュリティグループ変更通知** \n\n \n セキュリティグループ : <SecuritygroupId>が変更されたことを検知しました。\n\n 詳細は次のとおりです。\n - アカウントID : **<AwsAccountId>**\n\n- 発生時間 : **<time>(UTC)**\n\n- 変更ユーザー名 : **<userName>**\n\n- セキュリティグループID : **<SecuritygroupId>** \n\n**詳細は以下のリンクからご確認ください。(検知してからイベント履歴確認まで15分程度時間がかります。)**\n\n[CloudTrailイベントの詳細を確認する](https://<region>.console.aws.amazon.com/cloudtrailv2/home?region=<region>#/events/<eventId>)"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0",
"msteams": {
"width": "full",
"entities": [
{
"type": "mention",
"text": "\u003cat\u003e${MentionedUserName}\u003c/at\u003e",
"mentioned": {
"id": "${MentionedUserMailAddress}",
"name": "${MentionedUserName}"
}
}
]
}
}
}
]
}
RoleArn: !GetAtt IAMRole.Arn
EventBusName: default
EventsConnection:
Type: AWS::Events::Connection
Properties:
Name: !Sub ${SystemPrefix}-${EnvPrefix}-teams-conn
AuthorizationType: API_KEY
AuthParameters:
ApiKeyAuthParameters:
ApiKeyName: Content-Type
ApiKeyValue: application/json
EventsApiDestination:
Type: AWS::Events::ApiDestination
Properties:
Name: !Sub ${SystemPrefix}-${EnvPrefix}-teams-api-dest
ConnectionArn: !GetAtt EventsConnection.Arn
InvocationEndpoint: !Ref WebhookURL
HttpMethod: POST
InvocationRateLimitPerSecond: 300
テンプレート作成時のポイント
-
EventBridgeのルールの
EventPattern
で監視対象のリソースとイベント内容を指定しています。今回はセキュリティグループの変更通知であるAuthorizeSecurityGroupIngress
,AuthorizeSecurityGroupEgress
,RevokeSecurityGroupIngress
,RevokeSecurityGroupEgress
を指定しています。 -
EventBridgeのルールの
InputTransformer
でTeams通知する値の取得、およびメッセージ内容を設定しています。InputPathsMap
ではメールに通知する値を取得するために、EventBridge
に送られてきたJSONログイベントから特定の値を変数として抽出します。セキュリティグループの変更では以下のようなJSONログイベントが送られてきます。
JSONログイベント`AuthorizeSecurityGroupIngress`
{
"eventVersion": "1.09",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAVIM5J54ZWHCLMVYDN:iam-user-name",
"arn": "arn:aws:sts::123456789012:assumed-role/iam-user-name/iam-user-name",
"accountId": "123456789012",
"accessKeyId": "ASIAVIM5J54Z7FBYUMEV",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "AROAVIM5J54ZWHCLMVYDN",
"arn": "arn:aws:iam::123456789012:role/iam-user-name",
"accountId": "123456789012",
"userName": "iam-user-name"
},
"attributes": {
"creationDate": "2024-07-16T05:48:05Z",
"mfaAuthenticated": "true"
}
}
},
"eventTime": "2024-07-16T06:16:26Z",
"eventSource": "ec2.amazonaws.com",
"eventName": "AuthorizeSecurityGroupIngress",
"awsRegion": "ap-northeast-1",
"sourceIPAddress": "xx.xx.xx.xx",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"requestParameters": {
"groupId": "sg-06fd86ac3d58d8f4f",
"ipPermissions": {
"items": [
{
"ipProtocol": "tcp",
"fromPort": 443,
"toPort": 443,
"groups": {},
"ipRanges": {
"items": [
{
"cidrIp": "xx.xx.xx.xx/32"
}
]
},
"ipv6Ranges": {},
"prefixListIds": {}
}
]
}
},
"responseElements": {
"requestId": "f0b9432b-5257-4f98-b1f1-c2c602952f6c",
"_return": true,
"securityGroupRuleSet": {
"items": [
{
"groupOwnerId": "123456789012",
"groupId": "sg-06fd86ac3d58d8f4f",
"securityGroupRuleId": "sgr-08ee681fccc6c715d",
"isEgress": false,
"ipProtocol": "tcp",
"fromPort": 443,
"toPort": 443,
"cidrIpv4": "xx.xx.xx.xx/32"
}
]
}
},
"requestID": "f0b9432b-5257-4f98-b1f1-c2c602952f6c",
"eventID": "af1a19e5-1a90-4c9f-8ade-ae8d598922d8",
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "123456789012",
"eventCategory": "Management",
"tlsDetails": {
"tlsVersion": "TLSv1.3",
"cipherSuite": "TLS_AES_128_GCM_SHA256",
"clientProvidedHostHeader": "ec2.ap-northeast-1.amazonaws.com"
},
"sessionCredentialFromConsole": "true"
}
今回はTeams通知に含めたい項目として以下を入力パスに指定しました。
入力パス
AwsAccountId: '$.account'
SecuritygroupId: '$.detail.requestParameters.groupId'
eventId: '$.id'
time: '$.time'
userName: '$.detail.userIdentity.sessionContext.sessionIssuer.userName'
eventName: '$.detail.eventName'
region: '$.region'
InputTemplate
ではメッセージを設定しています。今回は箇条書きで出力されるように設定しています。表形式など他の形式にしたい場合は、下記のブログをご参考ください。
入力テンプレート
InputTemplate: !Sub |
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "\u003cat\u003e${MentionedUserName}\u003c/at\u003e \n\n# **セキュリティグループ変更通知** \n\n \n セキュリティグループ : <SecuritygroupId>が変更されたことを検知しました。\n\n 詳細は次のとおりです。\n - アカウントID : **<AwsAccountId>**\n\n- 発生時間 : **<time>**\n\n- 変更ユーザー名 : **<userName>**\n\n- セキュリティグループID : **<SecuritygroupId>**\n\n- CloudTrailイベントID : **<eventId>**\n\n- 変更内容 : **<eventName>**\n\n\n\n**セキュリティグループの確認方法** \n\nEC2コンソール画面の左メニューから「セキュリティグループ」を選択します。\n\n検索ウィンドウで「セキュリティグループID」を入力し、セキュリティグループが正しいことを確認してください。 \n\n \n**CloudTrailイベント履歴の確認方法** \n\nCloudTrailコンソール画面の左メニューから「イベント履歴」を選択します。 \n\n検索ウィンドウで「CloudTrailイベントID」を選択し、イベント詳細が確認できます。\n\n**CloudTrailイベントへのリンク**\n\n[CloudTrailイベントの詳細を確認する](https://<region>.console.aws.amazon.com/cloudtrailv2/home?region=<region>#/events/<eventId>)"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0",
"msteams": {
"width": "full",
"entities": [
{
"type": "mention",
"text": "\u003cat\u003e${MentionedUserName}\u003c/at\u003e",
"mentioned": {
"id": "${MentionedUserMailAddress}",
"name": "${MentionedUserName}"
}
}
]
}
}
}
]
}
いざ検証
CloudFromationでデプロイ
パラメータは、以下の値を入れます。
- SystemPrefix
- システム名
- EnvPrefix
- 環境名
- WebhookURL
- TeamsのWebhookURL(取得方法は、こちらのブログをご参照ください。)
- MentionedUserMailAddress
- メンション先のメールアドレス
- MentionedUserName
- メンション先の名前
2分ほどでデプロイが完了します。
セキュリティグループを変更
設定したセキュリティグループのインバウンドルールを編集してみます。
変更して数秒後、想定通りのTeams通知が届きました!
15分ほど経過後、Teamsに記載されているCloudTrailのリンクを選択します。ここからより詳細な情報が確認できますね。
さいごに
今回はセキュリティグループが変更・追加・削除されたことを検知して、Teamsに通知させる方法をご紹介しました。
最後までお読みいただきありがとうございました! どなたかのお役に立てれば幸いです。
以上、おつまみ(@AWS11077)でした!